package com.meilai.project.service.business.installOrder.impl;

import cn.afterturn.easypoi.excel.ExcelExportUtil;
import cn.afterturn.easypoi.excel.entity.ExportParams;
import cn.hutool.core.collection.CollUtil;
import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.meilai.project.constant.InstallTypeEnum;
import com.meilai.project.constant.WorkerSubmitStatusEnum;
import com.meilai.project.dto.app.WorkerSubmitDeviceDTO;
import com.meilai.project.dto.app.WorkerSubmitRepairDTO;
import com.meilai.project.dto.business.installOrder.WorkerRepairPointDTO;
import com.meilai.project.dto.business.installOrder.WorkerSubmitChangePhotoDTO;
import com.meilai.project.dto.business.installOrder.WorkerSubmitCheckDTO;
import com.meilai.project.dto.business.installOrder.WorkerSubmitListDTO;
import com.meilai.project.entity.business.installOrder.WorkOrder;
import com.meilai.project.entity.business.installOrder.WorkerSubmit;
import com.meilai.project.entity.business.installOrder.WorkerSubmitBreakdownTypeRelation;
import com.meilai.project.entity.business.installOrder.WorkerSubmitPhoto;
import com.meilai.project.entity.media.MediaPoint;
import com.meilai.project.entity.system.Config;
import com.meilai.project.entity.system.Dictionary;
import com.meilai.project.exception.CommonException;
import com.meilai.project.mapper.business.installOrder.WorkOrderInstallDetailMapper;
import com.meilai.project.mapper.business.installOrder.WorkOrderInstallDetailPointMapper;
import com.meilai.project.mapper.business.installOrder.WorkOrderMapper;
import com.meilai.project.mapper.business.installOrder.WorkerSubmitMapper;
import com.meilai.project.mapper.business.media.MediaPointMapper;
import com.meilai.project.mapper.system.DictionaryMapper;
import com.meilai.project.service.business.installOrder.WorkerSubmitBreakdownTypeRelationService;
import com.meilai.project.service.business.installOrder.WorkerSubmitPhotoService;
import com.meilai.project.service.business.installOrder.WorkerSubmitService;
import com.meilai.project.service.business.media.MediaPointService;
import com.meilai.project.service.business.sale.BillSaleService;
import com.meilai.project.service.system.ConfigService;
import com.meilai.project.service.system.DictionaryService;
import com.meilai.project.util.ThreadLocalUserUtil;
import com.meilai.project.vo.app.UploadBackVO;
import com.meilai.project.vo.business.installOrder.*;
import com.meilai.project.vo.system.UserVO;
import lombok.extern.log4j.Log4j2;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.poi.ss.usermodel.Workbook;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletResponse;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.*;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.function.Function;
import java.util.stream.Collectors;
import java.util.stream.Stream;

import static java.util.stream.Collectors.groupingBy;

/**
 * <p>
 * 工人提交 服务实现类
 * </p>
 *
 * @author 张驰
 * @since 2022-03-21
 */
@Service
@Log4j2
public class WorkerSubmitServiceImpl extends ServiceImpl<WorkerSubmitMapper, WorkerSubmit> implements WorkerSubmitService {

    private static final List<Long> specialMediaTypeId = Stream.of(5L, 6L, 7L, 9L, 11L).collect(Collectors.toList());
    @Autowired
    private WorkOrderMapper workOrderMapper;
    @Autowired
    private MediaPointMapper mediaPointMapper;
    @Autowired
    private WorkerSubmitPhotoService workerSubmitPhotoService;
    @Autowired
    private MediaPointService mediaPointService;
    @Autowired
    private WorkerSubmitBreakdownTypeRelationService breakdownTypeRelationService;
    @Autowired
    private WorkerSubmitMapper workerSubmitMapper;
    @Autowired
    private BillSaleService billSaleService;
    @Autowired
    private WorkOrderInstallDetailPointMapper workOrderInstallDetailPointMapper;
    @Autowired
    private WorkOrderInstallDetailMapper workOrderInstallDetailMapper;
    @Autowired
    private ConfigService configService;
    @Autowired
    private DictionaryService dictionaryService;

    /**
     * 处理查询的数据
     */
    private static WorkerSubmitExcelVO handleData(WorkerSubmitVO source) {
        WorkerSubmitExcelVO target = new WorkerSubmitExcelVO();
        // 设置工单类型
        switch (source.getInstall_type()) {
            case 1:
                target.setWork_order_type_name("新安装");
                break;
            case 2:
                target.setWork_order_type_name("上刊");
                break;
            case 3:
                target.setWork_order_type_name("下刊");
                break;
            case 4:
                target.setWork_order_type_name("巡检");
                break;
            case 5:
                target.setWork_order_type_name("维修");
                break;
            case 6:
                target.setWork_order_type_name("维修申报");
                break;
            default:
                target.setWork_order_type_name("");
                break;
        }
        target.setWorker_name(source.getWorker_name());
        target.setSaved_at(source.getSaved_at());
        target.setCreated_at(source.getCreated_at());
        target.setWork_order_name(source.getWork_order_name());
        target.setBuilding_area_name(source.getBuilding_area_name());
        target.setCode(source.getCode());
        target.setMedia_type_name(source.getMedia_type_name());
        if (source.getAb_type_id() == null) {
            target.setAb_type_name("");
        } else if (source.getAb_type_id().equals(57L)) {
            target.setAb_type_name("A面");
        } else if (source.getAb_type_id().equals(58L)) {
            target.setAb_type_name("B面");
        } else {
            target.setAb_type_name("");
        }
        if (source.getSize_width() != null && source.getSize_height() != null) {
            target.setSize(source.getSize_width() + "CM" + "*" + source.getSize_height() + "CM");
        } else {
            target.setSize("");
        }
        target.setAddress(source.getAddress());
        if (source.getBreakdown_type() == 1) {
            target.setFault("存在故障");
        } else {
            target.setFault("设备完好");
        }
        switch (source.getFlow_status()) {
            case 3:
                target.setStatus_name("待审核");
                break;
            case 4:
                target.setStatus_name("通过");
                break;
            case 2:
                target.setStatus_name("未通过");
                break;
            default:
                target.setStatus_name("");
                break;
        }
        return target;
    }

    @Override
    @Transactional
    public boolean changePhotoForApp(WorkerSubmitChangePhotoDTO dto) {
        WorkerSubmit la = getById(dto.getId());
        if (la == null) throw new CommonException("提交记录不存在，请联系管理员!");

        List<UploadBackVO> photos = dto.getFile_list();
        if (CollectionUtils.isEmpty(photos)) throw new CommonException("照片不能为空!");

        workerSubmitPhotoService.remove(Wrappers.<WorkerSubmitPhoto>lambdaQuery().eq(WorkerSubmitPhoto::getMedia_point_id, la.getMedia_point_id()).eq(WorkerSubmitPhoto::getWorker_submit_id, la.getId()));

        LocalDateTime now = LocalDateTime.now();
        List<WorkerSubmitPhoto> imgs = photos.stream().map(p -> {
            WorkerSubmitPhoto img = new WorkerSubmitPhoto();
            img.setMedia_point_id(la.getMedia_point_id());
            img.setWorker_submit_id(la.getId());
            img.setUrl(p.getUrl());
            img.setUpload_at(now);
            return img;
        }).collect(Collectors.toList());
        if (CollectionUtils.isNotEmpty(imgs)) workerSubmitPhotoService.saveBatch(imgs);

        return true;
    }

    @Override
    public WorkerSubmitForAppVO getAuditForApp(Long id) {
        WorkerSubmitForAppVO result = new WorkerSubmitForAppVO();

        WorkerSubmit la = getById(id);
        String detail = baseMapper.getDetailByWSID(id);
        if (detail == null) throw new CommonException("未找到该提交记录!");

        List<WorkerSubmitPhoto> photos = workerSubmitPhotoService.list(Wrappers.<WorkerSubmitPhoto>lambdaQuery().eq(WorkerSubmitPhoto::getMedia_point_id, la.getMedia_point_id()).eq(WorkerSubmitPhoto::getWorker_submit_id, id));
        if (CollectionUtils.isEmpty(photos)) throw new CommonException("数据错误，该记录无照片，请联系管理员!");

        result.setId(id);
        result.setCode(la.getCode());
        result.setDevice_id(la.getMedia_point_id());
        result.setDevice_info(detail);
        result.setFile_list(photos.stream().map(p -> {
            UploadBackVO vo = new UploadBackVO();
            vo.setId(p.getId());
            vo.setUrl(p.getUrl());
            return vo;
        }).collect(Collectors.toList()));

        return result;
    }

    @Override
    public List<WorkerSubmit> listByWorkOrderIds(List<Long> workOrderIds) {
        return baseMapper.listByWorkOrderIds(workOrderIds);
    }

    @Override
    public List<WorkerSubmit> listByWorkOrderId(Long workOrderId) {
        return baseMapper.listByWorkOrderIds(CollUtil.newArrayList(workOrderId));
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean addOneForApp(WorkerSubmitDeviceDTO dto) {
        log.info("工人提交：{}", JSON.toJSONString(dto));
        UserVO worker = ThreadLocalUserUtil.get();
        Long workerId = worker.getId();
        WorkOrder wo = workOrderMapper.selectById(dto.getWork_order_id());
        if (wo == null) throw new CommonException("工单不存在，请联系管理员");
        MediaPoint device = mediaPointMapper.selectById(dto.getDevice_id());
        if (device == null) throw new CommonException("设备不存在，请联系管理员");
        if (device.getDeleted_at() != null) throw new CommonException("该设备已注销，请联系管理员");

        // 提交code为空时，使用设备code覆盖
        if (StringUtils.isEmpty(dto.getCode())) dto.setCode(device.getCode());
        // 校验编号唯一
        checkCodeUniqueWithInFlow(dto.getCode(), dto.getDevice_id());

        // 组装提交对象
        WorkerSubmit cur = new WorkerSubmit();
        cur.setMedia_point_id(dto.getDevice_id());
        cur.setCode(dto.getCode());
        cur.setMedia_type_id(dto.getMedia_type_id());
        cur.setWork_order_id(dto.getWork_order_id());
        cur.setBuilding_type(dto.getBuilding_type());
        cur.setBuilding_area_id(dto.getBuilding_area_id());
        cur.setBuilding_number(dto.getBuilding_number());
        cur.setUnit_number(dto.getUnit_number());
        cur.setFloor(dto.getFloor() != null ? dto.getFloor().toString() : null);
        cur.setDoor_number(dto.getDoor_number());
        cur.setWorker_id(workerId);
        cur.setBreakdown_type(dto.getBreakdown_type());
        cur.setSize_height(dto.getSize_length());
        cur.setSize_width(dto.getSize_width());
        if ("A面".equals(dto.getMedia_feature())) cur.setAb_type_id(57L);
        if ("B面".equals(dto.getMedia_feature())) cur.setAb_type_id(58L);
        cur.setPic_type_id(dto.getPic_type());
        cur.setIs_light(dto.getIs_light());
        cur.setLocation(dto.getLocation());
        cur.setRemark(dto.getRemark());
        cur.setSaved_at(dto.getSaved_at());
        cur.setInstall_type(wo.getWork_order_type_id());
        // todo 增加逻辑 新安装的提交记录内部尺寸默认使用外部尺寸信息
        if (wo.getWork_order_type_id().equals(InstallTypeEnum.INSTALL.getInstallType())) {
            cur.setSize_height_inside(cur.getSize_height());
            cur.setSize_length_inside(cur.getSize_length());
            cur.setSize_width_inside(cur.getSize_width());
        }

        boolean isActive = device.getStatus() == 1;

        // 根据点位是否已激活，覆盖设备信息
        if (isActive) {
            // 已激活时，需要使用已有设备信息覆盖提交信息，防止工人修改
            cur.setCode(device.getCode());
            cur.setMedia_type_id(device.getMedia_type_id());
            cur.setBuilding_type(device.getBuilding_type());
            cur.setBuilding_area_id(device.getBuilding_area_id());
            cur.setBuilding_number(device.getBuilding_number());
            cur.setUnit_number(device.getUnit_number());
            cur.setFloor(device.getFloor());
            cur.setDoor_number(device.getDoor_number());
            cur.setSize_height(device.getSize_height());
            cur.setSize_width(device.getSize_width());
            cur.setAb_type_id(device.getAb_type_id());
            cur.setPic_type_id(device.getPic_type_id());
            cur.setIs_light(dto.getIs_light());
            cur.setLocation(dto.getLocation());
            cur.setFirst_install(0);
            cur.setSize_height_inside(device.getSize_height_inside());
            cur.setSize_length_inside(device.getSize_length_inside());
            cur.setSize_width_inside(device.getSize_width_inside());
        } else {
            // 未激活时，当前提交为第一次安装
            cur.setFirst_install(1);
        }

        // 不进流程
        cur.setFlow_applyer_id(workerId);
        cur.setFlow_applyer_org_id(worker.getMain_department_id());
        cur.setFlow_status(3);

        // 针对一个设备多次提交，
        WorkerSubmit latestSubmit = null;
        if (wo.getWork_order_type_id().equals(InstallTypeEnum.CHECK.getInstallType())) {
            // 巡检时，单独处理，查找“该工单”下的该设备的最新提交的一条审核信息（待审核或被退回），业务信息进行覆盖
            latestSubmit = getLatestSubmitNew(wo.getId(), cur.getMedia_point_id());
        } else {
            // “该工单类型”下的该设备的最新提交的一条审核信息（待审核或被退回），业务信息进行覆盖
            latestSubmit = getLatestSubmitNew(wo.getId(), cur.getMedia_point_id());
        }

        if(latestSubmit != null){
            if(latestSubmit.getFlow_status() == 4){ // 已通过
                throw new CommonException("该设备已提交且审核通过，无法重复提交");
            }else if(latestSubmit.getFlow_status() != 2 && latestSubmit.getFlow_status() != 3){
                latestSubmit = null;
            }
        }


        if (latestSubmit != null) {
            LocalDateTime _now = LocalDateTime.now();
            // 设置id
            cur.setId(latestSubmit.getId());
            cur.setUpdated_at(_now);
            cur.setCreated_at(_now);
            updateById(cur);
        } else {
            save(cur);
        }

        // 重新保存照片
        List<UploadBackVO> imgs = dto.getFile_list();
        List<WorkerSubmitPhoto> urls = new ArrayList<>();
        workerSubmitPhotoService.remove(new QueryWrapper<WorkerSubmitPhoto>().eq("worker_submit_id", cur.getId()));
        if (CollectionUtils.isNotEmpty(imgs)) {
            urls = imgs.stream().map(d -> {
                WorkerSubmitPhoto tem = new WorkerSubmitPhoto();
                tem.setUrl(d.getUrl());
                tem.setMedia_point_id(cur.getMedia_point_id());
                tem.setWorker_submit_id(cur.getId());
                return tem;
            }).collect(Collectors.toList());
            workerSubmitPhotoService.saveBatch(urls);
        }
        List<Long> reasonIds = dto.getBreakdown_type_ids();
        if (CollectionUtils.isNotEmpty(reasonIds)) {
            breakdownTypeRelationService.saveBatch(reasonIds.stream().map(d -> {
                WorkerSubmitBreakdownTypeRelation tem = new WorkerSubmitBreakdownTypeRelation();
                tem.setWorker_submit_id(dto.getDevice_id());
                tem.setBreakdown_type_id(d);
                return tem;
            }).collect(Collectors.toList()));
        }

//        // 生成流程字段，flow_type请自行对应dict_flow_type表中的id
//        FlowBusinessDataSuperEntity fbdse = WorkFlowUtil.getStartSuperDataEntity(workerId, null, 19, wo.getName()+"_设备审核_"+cur.getCode());
//        // 将流程字段复制到temp
//        BeanUtils.copyProperties(fbdse, cur);
//
//        try{
//            // 开始流程
//            int flowResult = new WorkFlowUtil<WorkerSubmit, WorkerSubmitMapper>(cur.getId(), workerId, WorkerSubmit.class)
//                    .Begin(0L, "", new WorkerSubmit());
//            if (flowResult == 1) {
//                // 开始流程成功
//                return true;
//            }else{
//                log.error("工人上传，开始流程失败，返回值不为1");
//                throw new CommonException("提交失败");
//            }
//        }catch (Exception e){
//            log.error("工人上传，开始流程失败", e);
//            throw new CommonException("提交失败");
//        }

        return true;

    }

    @Autowired
    private DictionaryMapper dictionaryMapper;

    @Override
    public Page<WorkerRepairPointVO> selectListNeedRepairPoint(WorkerRepairPointDTO searchDTO) {
        Page<WorkerRepairPointVO> page = searchDTO.createPage(WorkerRepairPointVO.class);
        List<WorkerRepairPointVO> workerRepairPointVOS = workerSubmitMapper.selectListNeedRepairPoint(page,searchDTO);

        if( CollUtil.isNotEmpty(workerRepairPointVOS)){
            Map<String,String> breakdown = new HashMap<String,String>();
            List<Dictionary> bdts = dictionaryMapper.selectList(new QueryWrapper<Dictionary>()
                    .select("id", "name").isNull("deleted_at").eq("status", 1)
                    .eq("level", 3).eq("rid", 1000).orderByAsc("sort","pid", "id"));
            bdts.forEach(d -> {
                breakdown.put(d.getId().toString(),d.getName());
            });

            Map<Long, RepairCountVO> countMap = workerSubmitMapper.queryDeviceReportCount().stream().collect(Collectors.toMap(RepairCountVO::getId, Function.identity()));
            workerRepairPointVOS.forEach(item -> {
                // 故障原因
                if( item.getBreakdown_type_ids() != null ){
                    String[] strIds = item.getBreakdown_type_ids().split(",");
                    List<String> strNames = new ArrayList<String>();
                    Arrays.stream(strIds).forEach(str -> {
                        if( breakdown.containsKey(str)){
                            strNames.add(breakdown.get(str));
                        }
                    });
                    item.setBreakdownName(String.join(",",strNames));
                }

//                if( breakdown.containsKey(item.getBreakdown_type_id())){
//                    item.setBreakdownName(breakdown.get(item.getBreakdown_type_id()));
//                }

                if (countMap.containsKey(item.getMedia_point_id())) {
                    item.setCount(countMap.get(item.getMedia_point_id()).getCount());
                } else {
                    item.setCount(0);
                }
            });
            List<Long> workSubmitIdList = workerRepairPointVOS.stream().map(WorkerRepairPointVO::getId).collect(Collectors.toList());
            List<WorkerSubmitPhoto> workerSubmitPhotos = workerSubmitPhotoService.listByWorkerSubmitIdList(workSubmitIdList);
            if (CollUtil.isNotEmpty(workerSubmitPhotos)) {
                Map<Long, List<WorkerSubmitPhoto>> photoMap = workerSubmitPhotos.stream().collect(Collectors.groupingBy(WorkerSubmitPhoto::getWorker_submit_id));
                for (WorkerRepairPointVO workerSubmitVO : workerRepairPointVOS) {
                    List<WorkerSubmitPhoto> photos = photoMap.get(workerSubmitVO.getId());
                    if (CollUtil.isEmpty(photos)) {
                        continue;
                    }
                    List<String> photoList = photos.stream().map(WorkerSubmitPhoto::getUrl).collect(Collectors.toList());
                    workerSubmitVO.setImgList(photoList);
                }
            }

        }
        page.setRecords(workerRepairPointVOS);
        return page;
    }

    @Override
    public int listTotal() {
        return workerSubmitMapper.listTotal();
    }

    // 查询该类型工单的，该设备的，待审批或被退回的，最新提交
    private WorkerSubmit getLatestSubmit(Integer work_order_type_id, Long media_point_id) {
        List<WorkerSubmit> submits = baseMapper.getWorkOrderCurTypePointSubmit(work_order_type_id, media_point_id);
        if (submits.size() == 0) return null;
        return submits.get(0);
    }

    // 查询该类型工单的，该设备的，最新提交
    private WorkerSubmit getLatestSubmitNew(Long work_order_id, Integer work_order_type_id, Long media_point_id) {
        List<WorkerSubmit> submits = baseMapper.getWorkOrderCurTypePointLatestSubmit(work_order_id, work_order_type_id, media_point_id);
        if (submits.size() == 0) return null;
        return submits.get(0);
    }

    // 查询该工单的，该设备的，待审批或被退回的，最新提交
    private WorkerSubmit getLatestSubmit(Long work_order_id, Long media_point_id) {
        List<WorkerSubmit> submits = baseMapper.getWorkOrderPointSubmit(work_order_id, media_point_id);
        if (submits.size() == 0) return null;
        return submits.get(0);
    }

    // 查询该工单的，该设备的，最新提交
    private WorkerSubmit getLatestSubmitNew(Long work_order_id, Long media_point_id) {
        List<WorkerSubmit> submits = baseMapper.getWorkOrderPointLatestSubmit(work_order_id, media_point_id);
        if (submits.size() == 0) return null;
        return submits.get(0);
    }

    // 检验设备编号唯一
    private void checkCodeUniqueWithInFlow(String code, Long mediaPointId) {
        if (StringUtils.isNotEmpty(code)) {
            List<MediaPoint> list = mediaPointService.list(new QueryWrapper<MediaPoint>().isNull("deleted_at").eq("code", code).ne("id", mediaPointId));
            if (CollectionUtils.isNotEmpty(list)) {
                log.error("设备编号已存在：" + code);
                throw new CommonException("设备编号已存在：" + code);
            }
        } else {
            log.error("设备编号为空");
            throw new CommonException("设备编号为空，请联系管理员！");
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean submitToApplyRepair(WorkerSubmitRepairDTO dto) {
        MediaPoint device = mediaPointMapper.selectById(dto.getDevice_id());
        if (device == null) throw new CommonException("该设备不存在，请确认");
        if (device.getDeleted_at() != null) throw new CommonException("该设备已注销，请确认");

        LocalDateTime _now = LocalDateTime.now();
        Long workerId = ThreadLocalUserUtil.get().getId();

        List<Long> reasonIds = dto.getBreakdown_type_ids();

        WorkerSubmit la = new WorkerSubmit();
        la.setId(null);
        la.setSort(1);
        la.setStatus(1);
        la.setDeleted_at(null);
        la.setCreated_at(_now);
        la.setUpdated_at(_now);
        la.setMedia_point_id(dto.getDevice_id());
        la.setBreakdown_type(1);
        la.setRemark(StringUtils.defaultString(dto.getRemark(), ""));
        la.setFirst_install(0);
        la.setInstall_type(6);
        la.setWorker_id(workerId);
        la.setFlow_status(4);
        // 多个故障原因
        if( CollectionUtils.isNotEmpty(reasonIds) ){
            la.setBreakdown_ids(reasonIds.stream().map(Object::toString)
                .collect(Collectors.joining(",")));
        }
        save(la);

        List<UploadBackVO> imgs = dto.getFile_list();
        if (CollectionUtils.isNotEmpty(imgs)) {
            workerSubmitPhotoService.saveBatch(imgs.stream().map(d -> {
                WorkerSubmitPhoto tem = new WorkerSubmitPhoto();
                tem.setMedia_point_id(la.getMedia_point_id());
                tem.setWorker_submit_id(la.getId());
                tem.setUrl(d.getUrl());
                return tem;
            }).collect(Collectors.toList()));
        }


        if (CollectionUtils.isNotEmpty(reasonIds)) {
            breakdownTypeRelationService.saveBatch(reasonIds.stream().map(d -> {
                WorkerSubmitBreakdownTypeRelation tem = new WorkerSubmitBreakdownTypeRelation();
                tem.setWorker_submit_id(la.getId());
                tem.setBreakdown_type_id(d);
                return tem;
            }).collect(Collectors.toList()));
        }

        return true;
    }

    @Override
    public void updateRepairStatus(Long workOrderId, List<Long> ids) {
        baseMapper.updateRepairStatus(workOrderId, ids);
    }

    @Override
    public List<WorkerSubmitStatusCountVO> workerSubmitStatusCount(Long workOrderId) {
        List<WorkerSubmitStatusCountVO> workerSubmitStatusCountVO = workerSubmitMapper.getWorkerSubmitStatusCount(workOrderId);
        WorkerSubmitStatusCountVO multiWorkerSubmitStatusCountVO = workerSubmitMapper.getMultiWorkerSubmitStatusCount(workOrderId);
        workerSubmitStatusCountVO.add(multiWorkerSubmitStatusCountVO);
        return workerSubmitStatusCountVO;
    }

    @Override
    public Page<WorkerSubmitVO> workerSubmitCheckList(WorkerSubmitListDTO workerSubmitListDTO) {
        List<WorkerSubmitVO> result;
        Page<WorkerSubmitVO> page = workerSubmitListDTO.createPage(WorkerSubmitVO.class);
        WorkerSubmitStatusEnum workerSubmitStatus = workerSubmitListDTO.getWorkerSubmitStatus();
        if (WorkerSubmitStatusEnum.MULTI_SUBMIT.equals(workerSubmitStatus)) {
            result = workerSubmitMapper.multiWorkerSubmitCheckList(page, workerSubmitListDTO);
        } else {
            result = workerSubmitMapper.workerSubmitCheckList(page, workerSubmitListDTO);
        }
        page.setRecords(result);
        if (CollUtil.isEmpty(result)) {
            return page;
        }
        List<Long> workSubmitIdList = result.stream().map(WorkerSubmitVO::getId).collect(Collectors.toList());
        List<WorkerSubmitPhoto> workerSubmitPhotos = workerSubmitPhotoService.listByWorkerSubmitIdList(workSubmitIdList);
        if (CollUtil.isNotEmpty(workerSubmitPhotos)) {
            Map<Long, List<WorkerSubmitPhoto>> photoMap = workerSubmitPhotos.stream().collect(Collectors.groupingBy(WorkerSubmitPhoto::getWorker_submit_id));
            for (WorkerSubmitVO workerSubmitVO : result) {
                List<WorkerSubmitPhoto> photos = photoMap.get(workerSubmitVO.getId());
                if (CollUtil.isEmpty(photos)) {
                    continue;
                }
                List<String> photoList = photos.stream().map(WorkerSubmitPhoto::getUrl).collect(Collectors.toList());
                workerSubmitVO.setPhotoList(photoList);
                workerSubmitVO.setPhotos(photos);
            }
        }
        Map<Long, List<WorkerSubmitBreakdownTypeRelation>> map = breakdownTypeRelationService.list(Wrappers.<WorkerSubmitBreakdownTypeRelation>lambdaQuery().in(WorkerSubmitBreakdownTypeRelation::getWorker_submit_id, workSubmitIdList)).stream().collect(Collectors.groupingBy(WorkerSubmitBreakdownTypeRelation::getWorker_submit_id));
        Map<Long, List<Dictionary>> dictMap = dictionaryService.listByCode("wxxg-gzyy").stream().collect(Collectors.groupingBy(Dictionary::getId));
        result.forEach(item -> {
            item.setBreakdown_type_name(new ArrayList<>());
            if (map.containsKey(item.getId())) {
                List<WorkerSubmitBreakdownTypeRelation> tmpList = map.get(item.getId());
                tmpList.forEach(tmp -> {
                    if (dictMap.containsKey(tmp.getBreakdown_type_id())) {
                        List<Dictionary> dictionaries = dictMap.get(tmp.getBreakdown_type_id());
                        item.getBreakdown_type_name().add(dictionaries.get(0).getName());
                    }
                });
            }
            List<WorkerOrderSelectOptionsVO> optionsVOList = new ArrayList<>();
            WorkerOrderSelectOptionsVO vo = new WorkerOrderSelectOptionsVO();
            vo.setId(item.getWork_order_id());
            vo.setName(item.getWork_order_name());
            optionsVOList.add(vo);
            item.setOptionsVOList(optionsVOList);
        });
        return page;
    }

    @Override
    public List<WorkerOrderSelectOptionsVO> workerOrderSelectOptions(Long workerSubmitId) {
        WorkerSubmit workerSubmit = getById(workerSubmitId);
        Long media_point_id = workerSubmit.getMedia_point_id();
        Integer install_type = workerSubmit.getInstall_type();
        InstallTypeEnum installTypeEnum = InstallTypeEnum.parse(install_type);
        List<WorkOrder> workOrders = workOrderMapper.selectForSelectOptions(install_type);
        //新安装的直接返回
        // todo 维修也直接返回
        if (InstallTypeEnum.INSTALL.equals(installTypeEnum) || InstallTypeEnum.REPAIR.equals(installTypeEnum)) {
            return convert(install_type, workOrders);
        }
        List<WorkOrder> includeSaleList = new ArrayList<>();
        List<WorkOrder> notIncludeSaleList = new ArrayList<>();
        for (WorkOrder workOrder : workOrders) {
            if (null == workOrder.getBill_sale_id()) {
                notIncludeSaleList.add(workOrder);
            } else {
                includeSaleList.add(workOrder);
            }
        }
        //包含销售单的，则此销售单里面要包含此点
        if (CollUtil.isNotEmpty(includeSaleList)) {
            List<Long> billSaleIdList = includeSaleList.stream().map(WorkOrder::getBill_sale_id).collect(Collectors.toList());
            List<Id2PointIdVO> id2PointIdVOList = billSaleService.listBillSaleMediaPoint(billSaleIdList);
            filter(media_point_id, includeSaleList, id2PointIdVOList, 2);
        }

        //不包含销售单的则是普通巡检单
        if (CollUtil.isNotEmpty(notIncludeSaleList)) {
            List<Long> workOrderIdList = notIncludeSaleList.stream().map(WorkOrder::getId).collect(Collectors.toList());
            List<Id2PointIdVO> id2PointIdVOList = workOrderInstallDetailPointMapper.listMediaPointByWorkOrderIds(workOrderIdList);
            filter(media_point_id, notIncludeSaleList, id2PointIdVOList, 1);
        }

        List<WorkOrder> result = new ArrayList<>();
        result.addAll(notIncludeSaleList);
        result.addAll(includeSaleList);

        return convert(install_type, result);
    }

    @Override
    public List<NewInstallBuildingAndMediaTypeVO> newInstallBuildingAndMediaTypeVO(Long workOrderId) {
        List<WorkOrderInstallDetailVO> workOrderInstallDetailVOS = workOrderInstallDetailMapper.queryByWorkOrderIdId(workOrderId);
        Map<Integer, List<WorkOrderInstallDetailVO>> buildingMap = workOrderInstallDetailVOS.stream().collect(Collectors.groupingBy(WorkOrderInstallDetailVO::getBuilding_area_id));
        List<NewInstallBuildingAndMediaTypeVO> result = new ArrayList<>();
        //保持顺序
        List<Integer> buildingIdList = workOrderInstallDetailVOS.stream().map(WorkOrderInstallDetailVO::getBuilding_area_id).distinct().collect(Collectors.toList());
        for (Integer buildingId : buildingIdList) {
            NewInstallBuildingAndMediaTypeVO item = new NewInstallBuildingAndMediaTypeVO();
            List<WorkOrderInstallDetailVO> installDetailVOList = buildingMap.get(buildingId);
            WorkOrderInstallDetailVO detailVO = installDetailVOList.get(0);
            item.setBuildingId(detailVO.getBuilding_area_id());
            item.setBuildName(detailVO.getBuildingName());
            result.add(item);

            List<NewInstallBuildingAndMediaTypeVO.InstallMediaTypeVO> mediaTypeVOList = new ArrayList<>();
            item.setMediaTypeVOList(mediaTypeVOList);
            for (WorkOrderInstallDetailVO workOrderInstallDetailVO : installDetailVOList) {
                NewInstallBuildingAndMediaTypeVO.InstallMediaTypeVO mediaTypeVO = new NewInstallBuildingAndMediaTypeVO.InstallMediaTypeVO();
                mediaTypeVO.setMediaTypeId(workOrderInstallDetailVO.getMedia_type_id());
                mediaTypeVO.setMediaTypeName(workOrderInstallDetailVO.getMediaTypeName());
                mediaTypeVOList.add(mediaTypeVO);
            }
        }
        return result;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void pass(WorkerSubmitCheckDTO workerSubmitCheckDTO) {
        List<WorkerSubmit> workerSubmitList = workerSubmitCheckDTO.getWorkerSubmitList();
        for (WorkerSubmit workerSubmit : workerSubmitList) {
            workerSubmit.setFlow_status(4);
            workerSubmit.setFlow_passed_at(LocalDateTime.now());
        }
        Map<Long, List<WorkerSubmit>> mediaPointMap = workerSubmitList.stream().collect(Collectors.groupingBy(WorkerSubmit::getMedia_point_id));
        List<Long> mediaPointIdList = workerSubmitList.stream().map(WorkerSubmit::getMedia_point_id).collect(Collectors.toList());
        List<MediaPoint> mediaPointList = mediaPointService.listByIds(mediaPointIdList);
        for (MediaPoint mediaPoint : mediaPointList) {
            WorkerSubmit workerSubmit = mediaPointMap.get(mediaPoint.getId()).get(0);
            fillData(mediaPoint, workerSubmit);
            //新安装的情况下允许修改这两个值
            if (workerSubmitCheckDTO.getInstallType().equals(InstallTypeEnum.INSTALL)) {
                mediaPoint.setBuilding_area_id(workerSubmit.getBuilding_area_id());
                mediaPoint.setMedia_type_id(workerSubmit.getMedia_type_id());
                // 新安装时，重置尺寸
                if (StringUtils.isBlank(mediaPoint.getSize_width_inside()) || StringUtils.isBlank(mediaPoint.getSize_length_inside())) {
                    mediaPoint.setSize_height_inside(workerSubmit.getSize_height_inside());
                    mediaPoint.setSize_width_inside(workerSubmit.getSize_width_inside());
                    mediaPoint.setSize_length_inside(workerSubmit.getSize_length_inside());
                }
                if (StringUtils.isBlank(mediaPoint.getSize_width()) || StringUtils.isBlank(mediaPoint.getSize_length())) {
                    mediaPoint.setSize_height(workerSubmit.getSize_height());
                    mediaPoint.setSize_width(workerSubmit.getSize_width());
                    mediaPoint.setSize_length(workerSubmit.getSize_length());
                }
                mediaPoint.setStatus(1);
            }
        }
        mediaPointService.updateBatchById(mediaPointList);
        updateBatchById(workerSubmitList);
    }

    private void fillData(MediaPoint mediaPoint, WorkerSubmit workerSubmit) {
        mediaPoint.setAb_type_id(workerSubmit.getAb_type_id());
        mediaPoint.setPic_type_id(workerSubmit.getPic_type_id());
        mediaPoint.setBuilding_type(workerSubmit.getBuilding_type());
        mediaPoint.setBuilding_number(workerSubmit.getBuilding_number());
        mediaPoint.setUnit_number(workerSubmit.getUnit_number());
        mediaPoint.setFloor(workerSubmit.getFloor());
        mediaPoint.setDoor_number(workerSubmit.getDoor_number());
        mediaPoint.setLocation(workerSubmit.getLocation());
        mediaPoint.setSize_length(workerSubmit.getSize_length());
        mediaPoint.setSize_width(workerSubmit.getSize_width());
        mediaPoint.setSize_height(workerSubmit.getSize_height());
        mediaPoint.setRemark(workerSubmit.getRemark());
        mediaPoint.setBreakdown_type(1 == workerSubmit.getBreakdown_type());
        mediaPoint.setIs_light(1 == workerSubmit.getIs_light());
        mediaPoint.setCode(workerSubmit.getCode());
    }

    @Override
    public void changeCheckStatus(Integer status, List<Long> ids) {
        if (CollUtil.isNotEmpty(ids)) {
            workerSubmitMapper.updateCheckStatus(status, ids);
        }
    }

    @Override
    public void delete(List<Long> ids) {
        if (CollUtil.isNotEmpty(ids)) {
            workerSubmitMapper.markDelete(ids);
        }
    }

    private void filter(Long media_point_id, List<WorkOrder> workOrderList, List<Id2PointIdVO> id2PointIdVOList, int type) {
        Map<Long, List<Id2PointIdVO>> id2PointMap = id2PointIdVOList.stream().collect(Collectors.groupingBy(Id2PointIdVO::getId));
        Iterator<WorkOrder> iterator = workOrderList.iterator();
        while (iterator.hasNext()) {
            WorkOrder workOrder = iterator.next();
            // todo 没有销售单时type是1 有销售单时type是2
            List<Id2PointIdVO> billSaleMediaPointVOList = id2PointMap.get(type == 1 ? workOrder.getId() : workOrder.getBill_sale_id());
            if (CollUtil.isNotEmpty(billSaleMediaPointVOList)) {
                Set<Long> mpIdSet = billSaleMediaPointVOList.stream().map(Id2PointIdVO::getPointId).collect(Collectors.toSet());
                if (mpIdSet.contains(media_point_id)) {
                    continue;
                }
            }
            iterator.remove();
        }
    }

    private List<WorkerOrderSelectOptionsVO> convert(Integer install_type, List<WorkOrder> workOrders) {
        String installTypeName = InstallTypeEnum.getName(install_type);
        List<WorkerOrderSelectOptionsVO> result = new ArrayList<>();
        for (WorkOrder workOrder : workOrders) {
            WorkerOrderSelectOptionsVO orderSelectOptionsVO = new WorkerOrderSelectOptionsVO();
            orderSelectOptionsVO.setId(workOrder.getId());
            orderSelectOptionsVO.setName("(" + installTypeName + ")" + workOrder.getName());
            orderSelectOptionsVO.setFromSaleBill(null == workOrder.getBill_sale_id());
            result.add(orderSelectOptionsVO);
        }
        return result;
    }

    @Override
    public Page<WorkerSubmitVO> page(Integer current_page, Integer page_size, LocalDate begin_time, LocalDate end_time, Long work_order_id, Long worker_id, List<Integer> work_order_type_ids, Integer status, String code, Long building_area_id, Long media_type_id, Boolean statistics, LocalDate begin_time_save, LocalDate end_time_save) {
        Page<WorkerSubmitVO> page = new Page<>(current_page, page_size);
        LocalDateTime beginDateTime = begin_time == null ? null : begin_time.atTime(0, 0, 0);
        LocalDateTime endDateTime = end_time == null ? null : end_time.atTime(23, 59, 59);
        LocalDateTime beginDateTimeSave = begin_time_save == null ? null : begin_time_save.atTime(0, 0, 0);
        LocalDateTime endDateTimeSave = end_time_save == null ? null : end_time_save.atTime(23, 59, 59);
        List<WorkerSubmitVO> list = baseMapper.page(page, beginDateTime, endDateTime, work_order_id, worker_id, work_order_type_ids, status, code, building_area_id, media_type_id, statistics, beginDateTimeSave, endDateTimeSave);
        List<Long> collect = list.stream().map(WorkerSubmitVO::getId).collect(Collectors.toList());
        if (CollectionUtils.isNotEmpty(collect)) {
            Map<Long, List<WorkerSubmitPhoto>> map = workerSubmitPhotoService.list(Wrappers.<WorkerSubmitPhoto>lambdaQuery().in(WorkerSubmitPhoto::getWorker_submit_id, collect)).stream().collect(groupingBy(WorkerSubmitPhoto::getWorker_submit_id));
            for (WorkerSubmitVO workerSubmitVO : list) {
                List<WorkerSubmitPhoto> workerSubmitPhotos = map.get(workerSubmitVO.getId());
                if (workerSubmitPhotos != null) {
                    workerSubmitVO.setPhotoList(workerSubmitPhotos.stream().map(WorkerSubmitPhoto::getUrl).collect(Collectors.toList()));
                }
            }
        }
        if (CollectionUtils.isNotEmpty(collect)) {
            Map<Long, List<WorkerSubmitBreakdownTypeRelation>> map = breakdownTypeRelationService.list(Wrappers.<WorkerSubmitBreakdownTypeRelation>lambdaQuery().in(WorkerSubmitBreakdownTypeRelation::getWorker_submit_id, collect)).stream().collect(Collectors.groupingBy(WorkerSubmitBreakdownTypeRelation::getWorker_submit_id));
            Map<Long, List<Dictionary>> dictMap = dictionaryService.listByCode("wxxg-gzyy").stream().collect(Collectors.groupingBy(Dictionary::getId));
            list.forEach(item -> {
                item.setBreakdown_type_name(new ArrayList<>());
                if (map.containsKey(item.getId())) {
                    List<WorkerSubmitBreakdownTypeRelation> tmpList = map.get(item.getId());
                    tmpList.forEach(tmp -> {
                        if (dictMap.containsKey(tmp.getBreakdown_type_id())) {
                            List<Dictionary> dictionaries = dictMap.get(tmp.getBreakdown_type_id());
                            item.getBreakdown_type_name().add(dictionaries.get(0).getName());
                        }
                    });
                }
            });
        }
        page.setRecords(list);
        return page;
    }

    @Override
    public void exportExcel(Integer current_page, Integer page_size, LocalDate begin_time, LocalDate end_time, Long work_order_id, Long worker_id, List<Integer> work_order_type_ids, Integer status, String code, Long building_area_id, Long media_type_id, HttpServletResponse response, Boolean statistics, LocalDate begin_time_save, LocalDate end_time_save) {
        LocalDateTime beginDateTime = begin_time == null ? null : begin_time.atTime(0, 0, 0);
        LocalDateTime endDateTime = end_time == null ? null : end_time.atTime(23, 59, 59);
        LocalDateTime beginDateTimeSave = begin_time_save == null ? null : begin_time_save.atTime(0, 0, 0);
        LocalDateTime endDateTimeSave = end_time_save == null ? null : end_time_save.atTime(23, 59, 59);
        List<WorkerSubmitVO> list = baseMapper.page(beginDateTime, endDateTime, work_order_id, worker_id, work_order_type_ids, status, code, building_area_id, media_type_id, statistics, beginDateTimeSave, endDateTimeSave);
        List<WorkerSubmitExcelVO> collect = list.stream().map(WorkerSubmitServiceImpl::handleData).collect(Collectors.toList());
        Workbook workbook = ExcelExportUtil.exportExcel(new ExportParams("安装统计导出", "安装统计"), WorkerSubmitExcelVO.class, collect);
        try {
            response.setContentType("application/octet-stream");
            response.setHeader("Content-Disposition", "attachment; filename=" + "安装统计" + ".xls");
            ServletOutputStream outputStream = response.getOutputStream();
            workbook.write(outputStream);
            outputStream.flush();
        } catch (Exception e) {
            throw new CommonException("导出失败");
        }
    }

    @Override
    public Page<WorkerSubmitCountVO> installCountPage(Integer current_page, Integer page_size, LocalDate startDate, LocalDate endDate, Long worker_id, Long media_type_id, Long work_order_type_id) {
        Page<WorkerSubmitCountVO> page = new Page<>(current_page, page_size);
        boolean isUnpublish = (work_order_type_id != null && work_order_type_id.equals(InstallTypeEnum.UNPUBLISH.getInstallType().longValue()));
        List<WorkerSubmitCountVO> list = baseMapper.installCountPage(null, startDate, endDate, worker_id, media_type_id, isUnpublish ? null : work_order_type_id);
        if (list != null && list.size() > 0) {
            Config interval_time = configService.configDetail("interval_time");
            // 获取分页中数据的开始和结束时间
            LocalDateTime endTime = list.get(0).getDate().atTime(23, 59, 59);
            LocalDateTime startTime = list.get(list.size() - 1).getDate().atStartOfDay();
            // 查询分页中的开始和结束时间段内所有的提交记录
            List<WorkerSubmitCountVO2> submitList = baseMapper.installCountByTime(startTime, endTime, Stream.of(2, 4).collect(Collectors.toList()), worker_id, media_type_id, isUnpublish ? null : work_order_type_id);
            Map<String, List<WorkerSubmitCountVO2>> dataMap = submitList.stream().collect(groupingBy(item -> item.getSaved_at().toLocalDate().format(DateTimeFormatter.ofPattern("yyyy-MM-dd")) + "_" + item.getWorker_id() + "_" + item.getMedia_type_id() + "_" + item.getWork_order_type_id()));
            // 循环统计数量
            for (WorkerSubmitCountVO vo : list) {
                InstallTypeEnum parse = InstallTypeEnum.parse(vo.getWork_order_type_id().intValue());
                vo.setWork_order_type_name(parse != null ? parse.getInstallTypeName() : "");
                String key = vo.getDate().format(DateTimeFormatter.ofPattern("yyyy-MM-dd")) + "_" + vo.getWorker_id() + "_" + vo.getMedia_type_id() + "_" + vo.getWork_order_type_id();
                if (dataMap.containsKey(key)) {
                    List<WorkerSubmitCountVO2> data = dataMap.get(key);
                    // 统计不通过数量
                    vo.setNo_pass_num((int) data.stream().filter(item -> item.getFlow_status() == 2).count());
                    // 如果是特殊类型 则统计楼盘个数
                    if (specialMediaTypeId.contains(vo.getMedia_type_id())) {
                        // 如果当前统计的是下刊
                        if (vo.getWork_order_type_id() == InstallTypeEnum.UNPUBLISH.getInstallType().longValue()) {
                            String key2 = vo.getDate().format(DateTimeFormatter.ofPattern("yyyy-MM-dd")) + "_" + vo.getWorker_id() + "_" + vo.getMedia_type_id() + "_" + InstallTypeEnum.PUBLISH.getInstallType();
                            List<WorkerSubmitCountVO2> data2 = dataMap.get(key2);
                            // 统计通过数量
                            Map<Long, List<WorkerSubmitCountVO2>> collect1 = data.stream().filter(item -> item.getFlow_status() == 4).collect(groupingBy(WorkerSubmitCountVO2::getBuilding_area_id));
                            if (data2 != null && data2.size() > 0) {
                                Map<Long, List<WorkerSubmitCountVO2>> collect2 = data2.stream().filter(item -> item.getFlow_status() == 4).collect(groupingBy(WorkerSubmitCountVO2::getBuilding_area_id));
                                AtomicInteger count = new AtomicInteger();
                                collect1.forEach((id_key, value) -> {
                                    if (!collect2.containsKey(id_key) || collect2.get(id_key) == null || collect2.get(id_key).size() == 0) {
                                        count.getAndIncrement();
                                    }
                                });
                                vo.setPass_num(count.get());
                            } else {
                                vo.setPass_num(collect1.size());
                            }
                        } else {
                            // 统计通过数量
                            Map<Long, List<WorkerSubmitCountVO2>> collect = data.stream().filter(item -> item.getFlow_status() == 4).collect(groupingBy(WorkerSubmitCountVO2::getBuilding_area_id));
                            vo.setPass_num(collect.size());
                        }
                    } else {
                        // 如果当前统计的是下刊
                        if (vo.getWork_order_type_id() == InstallTypeEnum.UNPUBLISH.getInstallType().longValue()) {
                            String key2 = vo.getDate().format(DateTimeFormatter.ofPattern("yyyy-MM-dd")) + "_" + vo.getWorker_id() + "_" + vo.getMedia_type_id() + "_" + InstallTypeEnum.PUBLISH.getInstallType();
                            List<WorkerSubmitCountVO2> data2 = dataMap.get(key2);
                            // 如果当天此工人对于此媒体类型有上刊数据的话
                            if (data2 != null && data2.size() > 0) {
                                AtomicInteger count = new AtomicInteger();
                                // 对今天此工人对于此媒体类型的下刊数据进行分组
                                Map<Long, List<WorkerSubmitCountVO2>> collect1 = data.stream().filter(item -> item.getFlow_status() == 4).collect(groupingBy(WorkerSubmitCountVO2::getMedia_point_id));
                                // 对今天此工人对于此媒体类型的上刊数据进行分组
                                Map<Long, List<WorkerSubmitCountVO2>> collect2 = data2.stream().filter(item -> item.getFlow_status() == 4).collect(groupingBy(WorkerSubmitCountVO2::getMedia_point_id));
                                collect1.forEach((id_key, value) -> {
                                    if (collect2.containsKey(id_key)) {// 如果今天有此点位的提交数据 则比较提交时间之间的间隔
                                        List<WorkerSubmitCountVO2> value2 = collect2.get(id_key);
//                                        if (value != null && value.size() == 1 && value2 != null && value2.size() == 1) {
//                                            LocalDateTime unPublishTime = value.get(0).getSaved_at();// 下刊时间
//                                            LocalDateTime publishTime = value2.get(0).getSaved_at();// 上刊时间
//                                            // 如果下刊时间加上设置的时间间隔没有超过上刊时间 则计入工作量
//                                            if (unPublishTime.plusHours(Integer.parseInt(interval_time.getParams())).isBefore(publishTime)) {
//                                                count.getAndIncrement();
//                                            }
//                                        } else {
//                                            throw new CommonException("统计出错，请联系管理员");
//                                        }
                                        if (value != null && value.size() > 0 && value2 != null && value2.size() > 0) {
                                            List<WorkerSubmitCountVO2> value3 = new ArrayList<>();
                                            value3.addAll(value);
                                            value3.addAll(value2);
                                            value3 = value3.stream().sorted(Comparator.comparing(WorkerSubmitCountVO2::getSaved_at)).collect(Collectors.toList());
                                            for (int i = 0; i < value3.size() - 1; i++) {
                                                WorkerSubmitCountVO2 cur = value3.get(i);
                                                WorkerSubmitCountVO2 next = value3.get(i+1);
                                                if(!(
                                                        cur.getInstall_type().equals(InstallTypeEnum.UNPUBLISH.getInstallType())
                                                                && next.getInstall_type().equals(InstallTypeEnum.PUBLISH.getInstallType())
                                                                && cur.getSaved_at() != null
                                                                && next.getSaved_at() != null
                                                                && (cur.getSaved_at().plusHours(Integer.parseInt(interval_time.getParams())).isAfter(next.getSaved_at())
                                                                        || cur.getSaved_at().plusHours(Integer.parseInt(interval_time.getParams())).isEqual(next.getSaved_at()))
                                                        )){
                                                    count.getAndIncrement();
                                                }
                                            }
                                        } else {
                                            throw new CommonException("统计出错，请联系管理员");
                                        }
                                    } else {
                                        count.getAndIncrement();
                                    }
                                });
                                vo.setPass_num(count.get());
                            } else {
                                vo.setPass_num((int) data.stream().filter(item -> item.getFlow_status() == 4).count());
                            }
                        } else {
                            vo.setPass_num((int) data.stream().filter(item -> item.getFlow_status() == 4).count());
                        }
                    }
                } else {
                    vo.setPass_num(0);
                    vo.setNo_pass_num(0);
                }
            }
        }

        List<WorkerSubmitCountVO> result = new ArrayList<>();
        if (isUnpublish && CollectionUtils.isNotEmpty(list)) {
            result = list.stream().filter(d -> d.getWork_order_type_id().equals(InstallTypeEnum.UNPUBLISH.getInstallType().longValue())).collect(Collectors.toList());
        } else {
            result = list;
        }
        page.setRecords(result);
        return page;
    }

    @Override
    public Page<WorkerSubmitVO3> installCountRecord(Integer current_page, Integer page_size, LocalDate startDate, LocalDate endDate, Long worker_id, Long building_area_id, Long work_order_type_id, Long customer_id) {
        Page<WorkerSubmitVO3> page = new Page<>(current_page, page_size);
        List<WorkerSubmitVO3> list = baseMapper.installCountRecord(page, startDate, endDate, worker_id, building_area_id, work_order_type_id, customer_id);
        // 拿到数据需要处理 未执行数、最近提交时间
        if (list != null && list.size() > 0) {
            List<Long> order_ids = list.stream().map(WorkerSubmitVO3::getWork_order_id).distinct().collect(Collectors.toList());
            // 查询分页中的开始和结束时间段内所有的提交记录
            List<WorkerSubmitCountVO2> submitList = workerSubmitMapper.getSubmitCountVO2List(order_ids);
            // 排序
            submitList = submitList.stream().sorted(Comparator.comparing(WorkerSubmit::getCreated_at).reversed()).collect(Collectors.toList());
            // 用来获取最新提交时间的map数据
            Map<String, List<WorkerSubmitCountVO2>> getLastSubmitTimeMap = submitList.stream().collect(groupingBy(item -> item.getCreated_at().toLocalDate().format(DateTimeFormatter.ofPattern("yyyy-MM-dd")) + "_" + item.getCustomer_id() + "_" + item.getBuilding_area_id() + "_" + item.getWork_order_type_id() + "_" + item.getWorker_id()));
            // 用来获取每天的未执行的数量数据
            Map<String, List<WorkerSubmitCountVO2>> getUnExecutedNumMap = submitList.stream().collect(groupingBy(item -> item.getWork_order_id() + "_" + item.getBuilding_area_id()));
            for (WorkerSubmitVO3 vo : list) {
                InstallTypeEnum parse = InstallTypeEnum.parse(vo.getWork_order_type_id().intValue());
                vo.setWork_order_type_name(parse != null ? parse.getInstallTypeName() : "");
                String lastSubmitTimeKey = vo.getDate().format(DateTimeFormatter.ofPattern("yyyy-MM-dd")) + "_" + vo.getCustomer_id() + "_" + vo.getBuilding_area_id() + "_" + vo.getWork_order_type_id() + "_" + vo.getWorker_id();
                String unExecutedNumKey = vo.getWork_order_id() + "_" + vo.getBuilding_area_id();
                // 设置最近的提交时间
                List<WorkerSubmitCountVO2> getLastSubmitTimeList = getLastSubmitTimeMap.get(lastSubmitTimeKey);
                if (getLastSubmitTimeList != null && getLastSubmitTimeList.size() > 0) {
                    vo.setLast_submit_time(getLastSubmitTimeList.get(getLastSubmitTimeList.size() - 1).getCreated_at());
                }
                // 设置未提交数
                List<WorkerSubmitCountVO2> getUnExecutedNumList = getUnExecutedNumMap.get(unExecutedNumKey);
                if (getUnExecutedNumList != null && getUnExecutedNumList.size() > 0) {

                    // 未提交数，由统计每天的，改为全部时间统计
                    // 去除重复提交
                    Map<String, WorkerSubmitCountVO2> countMap = new HashMap<>();
                    getUnExecutedNumList.forEach(item -> {
                        if (!countMap.containsKey(item.getWork_order_id() + "_" + item.getMedia_point_id())) {
                            countMap.put(item.getWork_order_id() + "_" + item.getMedia_point_id(), item);
                        }
                    });
                    vo.setUnexecuted_num(vo.getTotal_num() - countMap.size());

                    /*LocalDateTime closingTime = vo.getDate().atTime(23, 59, 59);
                    // 获取每天通过的数量
                    getUnExecutedNumList = getUnExecutedNumList.stream().filter(item -> item.getFlow_status() == 4 && (item.getCreated_at().isBefore(closingTime) || item.getCreated_at().equals(closingTime))).collect(Collectors.toList());
                    if (getLastSubmitTimeList != null && getLastSubmitTimeList.size() > 0) {
                        // 去除重复提交
                        Map<String, WorkerSubmitCountVO2> countMap = new HashMap<>();
                        getUnExecutedNumList.forEach(item -> {
                            if (!countMap.containsKey(item.getWork_order_id() + "_" + item.getMedia_point_id())) {
                                countMap.put(item.getWork_order_id() + "_" + item.getMedia_point_id(), item);
                            }
                        });
                        vo.setUnexecuted_num(vo.getTotal_num() - countMap.size());
                    } else {
                        vo.setUnexecuted_num(vo.getTotal_num());
                    }*/
                } else {
                    vo.setUnexecuted_num(vo.getTotal_num());
                }
            }
        }
        page.setRecords(list);
        return page;
    }

    @Override
    public Boolean replacePhoto(Long id, String oldUrl, String newUrl) {
        WorkerSubmitPhoto one = workerSubmitPhotoService.getById(id);
        one.setUrl(newUrl);
        one.setOld_url(oldUrl);
        return workerSubmitPhotoService.updateById(one);
    }
}
